<?php
/**
 * Created by PhpStorm.
 * User: xuechunxuan
 * Date: 2018/10/18
 * Time: 11:05
 */
namespace app\index\model;

use think\Db;

class Pay extends Base{
    public function __construct($data = [])
    {
      $this->setTableName("user_pay_detail");
    }
    public function pay($url, $obj)
    {
        $obj['nonce_str'] = $this->create_noncestr();
        $stringA = $this->formatQueryParaMap($obj, false);
        $stringSignTemp = $stringA . "&key=" . config("PARTNERKEY");
        $sign = strtoupper(md5($stringSignTemp));
        $obj['sign'] = $sign;
        $postXml = $this->arrayToXml($obj);
        $responseXml = $this->curl_post_ssl($url, $postXml);
        return $responseXml;
    }

    public function create_noncestr($length = 32)
    {
        $chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
        $str = "";
        for ($i = 0; $i < $length; $i++) {
            $str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
        }
        return $str;
    }

    public function formatQueryParaMap($paraMap, $urlencode)
    {
        $buff = "";
        ksort($paraMap);
        foreach ($paraMap as $k => $v) {
            if (null != $v && "null" != $v && "sign" != $k) {
                if ($urlencode) {
                    $v = urlencode($v);
                }
                $buff .= $k . "=" . $v . "&";
            }
        }
        $reqPar = "";
        if (strlen($buff) > 0) {
            $reqPar = substr($buff, 0, strlen($buff) - 1);
        }
        return $reqPar;
    }

//数组转XML
    public function arrayToXml($arr)
    {
        $xml = "<xml>";
        foreach ($arr as $key => $val) {
            if (is_numeric($val)) {
                $xml .= "<" . $key . ">" . $val . "</" . $key . ">";
            } else {
                $xml .= "<" . $key . "><![CDATA[" . $val . "]]></" . $key . ">";
            }
        }
        $xml .= "</xml>";
        return $xml;
    }

    public function curl_post_ssl($url, $vars, $second = 30)
    {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_TIMEOUT, $second);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);

        curl_setopt($ch, CURLOPT_SSLCERT, ROOT_PATH . 'public/static/cert/apiclient_cert.pem');
        curl_setopt($ch, CURLOPT_SSLKEY, ROOT_PATH . 'public/static/cert/apiclient_key.pem');
        curl_setopt($ch, CURLOPT_CAINFO, ROOT_PATH . 'public/static/cert/rootca.pem');

        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $vars);
        $data = curl_exec($ch);
        if ($data) {
            curl_close($ch);
            return $data;
        } else {
            $error = curl_errno($ch);
            echo "call faild, errorCode:$error\n";
            curl_close($ch);
            return $error;
        }
    }

    /*
    * 支付选中订单
    * @param $ids|id组
    * */
    public function payWeiXinTX($orderId)
    {
        $payInfo=Db::name($this->getTableName())->where(['id'=>$orderId,'status'=>1])->find();
        $url = 'https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers';//支付链接
        $returnStr = "";
        $obj1 = array();
            $money = (int)$payInfo['amount'];//(int)$payInfo['amount']
            $obj1['openid'] = $payInfo['open_id'];
            $obj1['amount'] = $money;
            $obj1['desc'] = config("TITLE") . "id:" . $payInfo['user_id'] . "提现.";
            $obj1['mch_appid'] = config("PAY_APP_ID");//appid
            $obj1['mchid'] = config("PAY_MCHID");//商户编号
            $obj1['partner_trade_no'] = $payInfo['user_id'] . date('Ymd') . $payInfo['id'];
            $obj1['spbill_create_ip'] = $_SERVER['REMOTE_ADDR'];
            $obj1['check_name'] = "NO_CHECK";
            $result = $this->pay($url, $obj1);//判定返回值
            if ($this->cut($result, "<result_code>", "</result_code>") == '<![CDATA[FAIL]]>') {
                $msg = str_replace("<", "", $this->cut($result, "<err_code_des>", "</err_code_des>"));
                $msg = str_replace("<", "", $msg);
                $returnStr = $returnStr . $payInfo['user_id'] . "提现失败,".$msg;
                $data = [
                    "status" => 3,
                    'wx_result_msg' => $msg,
                    'pay_time' => time()
                ];
                Db::name($this->getTableName())->where("id", $payInfo['id'])->update($data);//标记为未支付
            } else {
                $returnStr = "提现成功";
                $payment_no = str_replace(array("<![CDATA[", "]]>"), "", $this->cut($result, "<payment_no>", "</payment_no>"));//获取微信订单号
                $data = [
                    "status" => 2,
                    'pay_time' => time(),
                    "wx_result_msg" => "已支付",
                    "wx_number" => $payment_no];
                // 启动事务
                Db::startTrans();
                try{
                    Db::name($this->getTableName())->where("id", $payInfo['id'])->update($data);
                    //进行分成
                    $this->subordinate(['user_id'=>$payInfo['user_id'],'amount'=>$payInfo['amount']]);
                    // 提交事务
                    Db::commit();
                } catch (\Exception $e) {
                    // 回滚事务

                    Db::rollback();
                }

            }
        return $returnStr;
    }

    /*
     * 判断用户当天是否提现过
     * @param $userId int | 用户id
     * */
    public function getUserToDayPay($userId){
        return Db::name($this->getTableName())
            ->where("pay_time>".$this->getZeroTime()." and pay_time<".$this->getEndTime()." and user_id=".$userId)
            ->find();

    }
    /*
     * 判断用户是否有未支付订单
     * */
    public function getUserUnPay($userId){
        return Db::name($this->getTableName())
            ->where(['status'=>1,"user_id"=>$userId])
            ->find();
    }

    /*
     * 创建提现订单并扣除对应金额优先扣除分成金额
     * */
    public function add($data){
        // 启动事务
        Db::startTrans();
        try {
            $result= Db::name($this->getTableName())->insertGetId($data);
            Db::name("user")->where(['openid'=>$data['open_id']])->setDec("fall_into_amount",$data['no_fall_into_amount']);
            Db::name("user")->where(['openid'=>$data['open_id']])->setDec("amount",($data['amount']-$data['no_fall_into_amount']));
            // 提交事务
            Db::commit();
        } catch (\Exception $e) {
            $result=false;
            // 回滚事务
            Db::rollback();
        }
        return $result;
    }

    /*
     * 更新订单状态
     * */
    public function edit($data){
        if($data['status']==2){
            // 启动事务
            Db::startTrans();
            try {
                //标记为已支付并计算分成
                Db::name($this->getTableName())->update($data);
                $this->subordinate($data);
                // 提交事务
                Db::commit();
            } catch (\Exception $e) {
                // 回滚事务
                Db::rollback();
            }
        }else{
            return Db::name($this->getTableName())->update($data);
        }
    }

    /*
     * 进行上级分成
     * */
    public function subordinate($data){
       $pPath=Db::name("user")->where(['id'=>$data['user_id']])->field("p_path")->find()['p_path'];
       if($pPath){
           $pPathArr=explode("-",$pPath);
           unset($pPathArr[0]);//移除第一位空数据
           unset($pPathArr[count($pPathArr)]);//移除最后一位空数据
           $ci=20;//一级百分之20
           $i=1;
            foreach ($pPathArr as $key){
                $fallIntoAmount=$data['amount']*($ci/100);
                $detailData=[
                    'user_id'=>$data['user_id'],
                    'get_user_id'=>$pPathArr[$i],
                    'amount'=>$fallIntoAmount,
                    'add_time'=>time()
                ];
             Db::name("user")->where(['id'=>$pPathArr[$i]])->setInc("fall_into_amount",$fallIntoAmount);
             Db::name("user")->where(['id'=>$pPathArr[$i]])->setInc("fall_into_amount_count",$fallIntoAmount);
             Db::name("user_subordinate_detail")->insert($detailData);
                $ci=$ci/2;//每一级减少一半的分成
                $i++;
            }
       }
    }

    /*
   * 剪取网页内容
   * */
    public function cut($from, $start, $end, $lt = false, $gt = false)
    {
        $str = explode($start, $from);
        if (isset($str['1']) && $str['1'] != '') {
            $str = explode($end, $str['1']);
            $strs = $str['0'];
        } else {
            $strs = '';
        }
        if ($lt) {
            $strs = $start . $strs;
        }
        if ($gt) {
            $strs .= $end;
        }
        return $strs;
    }

    /*
 * 获取用户画像
 * */
    public function getUserShareViewByTime($openid){
        return Db::name("user_share_detail")
            ->field("FROM_UNIXTIME(add_time,'%Y-%m-%d %H') time,count(id) num ")
            ->where(["openid"=>$openid])
            ->group("time")
            ->order("id desc")
            ->select();
    }
}